package com.ruoyi.system.service.impl;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.dto.Compute_detail_sum;
import com.ruoyi.system.domain.exp.DeliveryExport;
import com.ruoyi.system.domain.exp.SendExport;
import com.ruoyi.system.domain.res.deliveryDetail.DeliveryDay_res;
import com.ruoyi.system.domain.res.deliveryDetail.DetailNum_res;
import com.ruoyi.system.domain.vo.DeliveryVO;
import com.ruoyi.system.mapper.*;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.system.service.IDeliveryService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * 采购单Service业务层处理
 *
 * @author ruoyi
 * @date 2024-09-05
 */
@Service
public class DeliveryServiceImpl implements IDeliveryService {
    @Resource
    private DeliveryMapper deliveryMapper;
    @Resource
    private ProjectLogMapper projectLogMapper;
    @Resource
    private ProjectLogDetailMapper projectLogDetailMapper;
    @Resource
    private DeliveryDetailMapper deliveryDetailMapper;
    @Resource
    private ComputeDetailMapper computeDetailMapper;
    @Resource
    private SysDeptMapper sysDeptMapper;
    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private TypeMapper typeMapper;
    @Resource
    private SpecMapper specMapper;
    @Resource
    private BrandMapper brandMapper;
    @Resource
    private ProjectMapper projectMapper;
    @Resource
    private CateMapper cateMapper;

    /**
     * 查询采购单
     *
     * @param id 采购单主键
     * @return 采购单
     */
    @Override
    public DeliveryVO selectDeliveryById(Long id) {
        Delivery delivery = deliveryMapper.selectDeliveryById(id);

        format(delivery);


        return formatDelivery(delivery, null, null, null, null);
    }

    /**
     * 查询采购单列表
     *
     * @param delivery 采购单
     * @return 采购单
     */
    @Override
    public List<Delivery> selectDeliveryList(Delivery delivery) {

        if (delivery.getParams() != null) {
            if (delivery.getParams().containsKey("sendTimeStart") && delivery.getParams().containsKey("sendTimeEnd")) {
                if (delivery.getParams().get("sendTimeStart") != null && !"".equals(delivery.getParams().get("sendTimeStart"))
                        && delivery.getParams().get("sendTimeEnd") != null && !"".equals(delivery.getParams().get("sendTimeEnd"))) {
                    delivery.getParams().put("sendTimeStart", delivery.getParams().get("sendTimeStart") + " 00:00:00");
                    delivery.getParams().put("sendTimeEnd", delivery.getParams().get("sendTimeEnd") + " 23:59:59");
                }

            }
        }


        List<Delivery> deliveries = deliveryMapper.selectDeliveryList(delivery);
        deliveries.forEach(this::format);
        return deliveries;
    }

    private void format(Delivery item) {
        SysDept school = sysDeptMapper.selectDeptById(item.getSchoolId());
        SysDept company = sysDeptMapper.selectDeptById(item.getDeptId());
        if (school != null) {
            item.setSchoolName(school.getDeptName());
            if (school.getPhone() == null || "".equals(school.getPhone())) {
                item.setSchoolPhone(school.getLeader());
            } else {
                item.setSchoolPhone(school.getPhone());
            }

        }
        if (company != null) {
            item.setDeptName(company.getDeptName());
        }
//        DetailNum_res detailNum = deliveryDetailMapper.getDetailNum(item.getId());
//        if (detailNum != null) {
//            item.setNum(detailNum.getNum());
//            item.setShouNum(detailNum.getShouNum());
//            item.setWeiNum(detailNum.getWeiNum());
//        }
        item.setCount_all(deliveryDetailMapper.getDetailCountById(item.getId(), null));
        item.setCount_ok(deliveryDetailMapper.getDetailCountById(item.getId(), 1));

    }

    private DeliveryVO formatDelivery(Delivery item, Map<Long, Cate> cateMap, Map<Long, Type> typeMap, Map<Long, Spec> specMap, Map<Long, Brand> brandMap) {
        DeliveryVO deliveryVO = new DeliveryVO();
        BeanUtils.copyProperties(item, deliveryVO);

        List<DeliveryDetail> detailList = deliveryDetailMapper.selectDeliveryDetailList(new DeliveryDetail() {{
            setDeliveryId(item.getId());
        }});

        detailList.forEach(item_in -> {
            Type type = null;
            if (typeMap != null) {
                if (typeMap.containsKey(item_in.getTypeId())) {
                    type = typeMap.get(item_in.getTypeId());
                }
            } else {
                type = typeMapper.selectTypeById(item_in.getTypeId());
            }
            if (type != null) {
                item_in.setTypeName(type.getName());

                Cate cate = null;
                if (cateMap != null) {
                    if (cateMap.containsKey(type.getCateId())) {
                        cate = cateMap.get(type.getCateId());
                    }
                } else {
                    cate = cateMapper.selectCateById(type.getCateId());
                }

                if (cate != null) {
                    item_in.setCateName(cate.getName());
                }
            }

            Spec spec = null;
            if (specMap != null) {
                if (specMap.containsKey(item_in.getSpecId())) {
                    spec = specMap.get(item_in.getSpecId());
                }
            } else {
                spec = specMapper.selectSpecById(item_in.getSpecId());
            }

            if (spec != null) {
                item_in.setSpecName(spec.getName());
            }

            Brand brand = null;
            if (brandMap != null) {
                if (brandMap.containsKey(item_in.getBrandId())) {
                    brand = brandMap.get(item_in.getBrandId());
                }
            } else {
                brand = brandMapper.selectBrandById(item_in.getBrandId());
            }

            if (brand != null) {
                item_in.setBrandName(brand.getName());
            }
        });

        deliveryVO.setDetails(detailList);
        return deliveryVO;
    }

    /**
     * 根据日期查询配送单
     */
    @Override
    public List<DeliveryDay_res> selectDeliveryDay(Delivery delivery) {
        return deliveryMapper.selectDeliveryList(delivery).stream().map(item -> {
            DeliveryDay_res res = new DeliveryDay_res();
            SysDept school = sysDeptMapper.selectDeptById(item.getSchoolId());
            if (school != null) {
                res.setSchoolName(school.getDeptName());
            }
            SysDept company = sysDeptMapper.selectDeptById(item.getDeptId());
            if (company != null) {
                res.setDeptName(company.getDeptName());
            }
            res.setCount_all(deliveryDetailMapper.getDetailCountById(item.getId(), null));
            res.setCount_ok(deliveryDetailMapper.getDetailCountById(item.getId(), 1));
            return res;
        }).collect(Collectors.toList());
    }

    /**
     * 查询采购单列表_export
     */
    @Override
    public List<DeliveryExport> selectDeliveryList_forExport(Delivery delivery) {
        if (delivery.getParams() != null) {
            if (delivery.getParams().containsKey("sendTimeStart") && delivery.getParams().containsKey("sendTimeEnd")) {
                if (delivery.getParams().get("sendTimeStart") != null && !"".equals(delivery.getParams().get("sendTimeStart"))
                        && delivery.getParams().get("sendTimeEnd") != null && !"".equals(delivery.getParams().get("sendTimeEnd"))) {
                    delivery.getParams().put("sendTimeStart", delivery.getParams().get("sendTimeStart") + " 00:00:00");
                    delivery.getParams().put("sendTimeEnd", delivery.getParams().get("sendTimeEnd") + " 23:59:59");
                }

            }
        }


        List<Delivery> deliveries = deliveryMapper.selectDeliveryList(delivery);
        List<DeliveryVO> voList = new ArrayList<>(10);

        Map<Long, Cate> cateMap = cateMapper.selectCateList(new Cate()).stream().collect(Collectors.toMap(Cate::getId, t -> t));
        Map<Long, Type> typeMap = typeMapper.selectTypeList(new Type()).stream().collect(Collectors.toMap(Type::getId, t -> t));
        Map<Long, Spec> specMap = specMapper.selectSpecList(new Spec()).stream().collect(Collectors.toMap(Spec::getId, t -> t));
        Map<Long, Brand> brandMap = brandMapper.selectBrandList(new Brand()).stream().collect(Collectors.toMap(Brand::getId, t -> t));

        deliveries.forEach(item -> {
            format(item);
            voList.add(formatDelivery(item, cateMap, typeMap, specMap, brandMap));
        });

        List<DeliveryExport> exportList = new ArrayList<>(10);
        voList.forEach(item -> {
            if (item.getDetails() != null && !item.getDetails().isEmpty()) {
                item.getDetails().forEach(item_in -> {
                    DeliveryExport deliveryExport = new DeliveryExport();

                    deliveryExport.setSchoolName(item.getSchoolName());
                    deliveryExport.setDeptName(item.getDeptName());
                    deliveryExport.setSendTime(DateUtils.parseDateToStr("yyyy-MM-dd", item.getSendTime()));
                    deliveryExport.setMoney(String.valueOf(item.getMoney()));
                    deliveryExport.setTypeName(item_in.getTypeName());
                    deliveryExport.setSpecName(item_in.getSpecName());
                    deliveryExport.setBrandName(item_in.getBrandName());
                    deliveryExport.setNum(String.valueOf(item_in.getNum()));
                    deliveryExport.setPrice(String.valueOf(item_in.getPrice()));
                    deliveryExport.setShowNum(String.valueOf(item_in.getShouNum()));
                    deliveryExport.setWeiNum(String.valueOf(item_in.getWeiNum()));
                    deliveryExport.setjMoney(String.valueOf(item_in.getjMoney()));
                    deliveryExport.setMoney_in(String.valueOf(item_in.getMoney()));
                    deliveryExport.setRemark(item_in.getRemark());

                    exportList.add(deliveryExport);
                });
            }
        });


        return exportList;
    }

    /**
     * 查询采购单列表_sendExport
     */
    @Override
    public List<SendExport> selectDeliveryList_forSendExport(Delivery delivery) {
        if (delivery.getParams() != null) {
            if (delivery.getParams().containsKey("sendTimeStart") && delivery.getParams().containsKey("sendTimeEnd")) {
                if (delivery.getParams().get("sendTimeStart") != null && !"".equals(delivery.getParams().get("sendTimeStart"))
                        && delivery.getParams().get("sendTimeEnd") != null && !"".equals(delivery.getParams().get("sendTimeEnd"))) {
                    delivery.getParams().put("sendTimeStart", delivery.getParams().get("sendTimeStart") + " 00:00:00");
                    delivery.getParams().put("sendTimeEnd", delivery.getParams().get("sendTimeEnd") + " 23:59:59");
                }

            }
        }


        List<Delivery> deliveries = deliveryMapper.selectDeliveryList(delivery);
        List<DeliveryVO> voList = new ArrayList<>(10);

        Map<Long, Cate> cateMap = cateMapper.selectCateList(new Cate()).stream().collect(Collectors.toMap(Cate::getId, t -> t));
        Map<Long, Type> typeMap = typeMapper.selectTypeList(new Type()).stream().collect(Collectors.toMap(Type::getId, t -> t));
        Map<Long, Spec> specMap = specMapper.selectSpecList(new Spec()).stream().collect(Collectors.toMap(Spec::getId, t -> t));
        Map<Long, Brand> brandMap = brandMapper.selectBrandList(new Brand()).stream().collect(Collectors.toMap(Brand::getId, t -> t));

        deliveries.forEach(item -> {
            format(item);
            voList.add(formatDelivery(item, cateMap, typeMap, specMap, brandMap));
        });

        List<SendExport> exportList = new ArrayList<>(10);
        voList.forEach(item -> {
            if (item.getDetails() != null && !item.getDetails().isEmpty()) {
                item.getDetails().forEach(item_in -> {
                    SendExport deliveryExport = new SendExport();

                    deliveryExport.setSchoolName(item.getSchoolName());
                    deliveryExport.setDeptName(item.getDeptName());
                    deliveryExport.setSendTime(DateUtils.parseDateToStr("yyyy-MM-dd", item.getSendTime()));
                    deliveryExport.setSendMoney(String.valueOf(item.getSendMoney()));
                    deliveryExport.setTypeName(item_in.getTypeName());
                    deliveryExport.setSpecName(item_in.getSpecName());
                    deliveryExport.setBrandName(item_in.getBrandName());
                    deliveryExport.setNum(String.valueOf(item_in.getNum()));
                    deliveryExport.setSendPrice(String.valueOf(item_in.getSendPrice()));
                    deliveryExport.setShowNum(String.valueOf(item_in.getShouNum()));
                    deliveryExport.setWeiNum(String.valueOf(item_in.getWeiNum()));
                    deliveryExport.setjMoneySend(String.valueOf(item_in.getjMoneySend()));
                    deliveryExport.setSendMoney_in(String.valueOf(item_in.getSendMoney()));
                    deliveryExport.setRemark(item_in.getRemark());

                    exportList.add(deliveryExport);
                });
            }
        });


        return exportList;
    }

    /**
     * 新增采购单
     *
     * @param delivery 采购单
     * @return 结果
     */
    @Override
    public int insertDelivery(Delivery delivery) {
        delivery.setCreateTime(DateUtils.getNowDate());

        if (delivery.getParams().get("details") == null) {
            throw new ServiceException("未填写采购物品");
        }
        List<DeliveryDetail> detailList = JSON.parseArray(JSON.toJSONString(delivery.getParams().get("details")), DeliveryDetail.class);

        delivery.setId(Long.valueOf(DateUtils.dateTimeNow() + RandomStringUtils.random(4, false, true)));
        if (delivery.getUserId() != null) {
            SysUser sysUser = sysUserMapper.selectUserById(delivery.getUserId());
            delivery.setDeptId(sysUser.getDeptId());
        }

        delivery.setType(1L);
        delivery.setSendMoney(delivery.getMoney());

        int i = deliveryMapper.insertDelivery(delivery);

        detailList.forEach(item -> {
            item.setSchoolId(delivery.getSchoolId());
            item.setDeliveryId(delivery.getId());
            item.setSendPrice(item.getPrice());
            item.setSendMoney(item.getMoney());
            item.setjMoneySend(item.getjMoney());
            item.setCreateTime(delivery.getCreateTime());
        });

        deliveryDetailMapper.insertDeliveryDetailBatch(new HashMap<String, Object>() {{
            put("details", detailList);
        }});

        return i;
    }

    /**
     * 修改采购单
     *
     * @param delivery 采购单
     * @return 结果
     */
    @Override
    public int updateDelivery(Delivery delivery) {

        Integer version = deliveryMapper.selectDeliveryVersion(delivery.getId());
        if (!version.equals(delivery.getUpdateLock())) {
            throw new ServiceException("当前数据正在更新，请刷新后重新提交修改");
        }

        delivery.setUpdateTime(DateUtils.getNowDate());
        if (delivery.getParams().get("details") == null) {
            throw new ServiceException("未填写采购物品");
        }
        List<DeliveryDetail> detailList = JSON.parseArray(JSON.toJSONString(delivery.getParams().get("details")), DeliveryDetail.class);
        if (delivery.getUserId() != null) {
            SysUser sysUser = sysUserMapper.selectUserById(delivery.getUserId());
            delivery.setDeptId(sysUser.getDeptId());
        }


//        deliveryDetailMapper.deleteDeliveryDetailByDeliveryId(delivery.getId());

        List<DeliveryDetail> addList = new ArrayList<>(10);
        List<DeliveryDetail> updateList = new ArrayList<>(10);

        detailList.forEach(item -> {
            item.setSchoolId(delivery.getSchoolId());
            item.setDeliveryId(delivery.getId());
            item.setSendPrice(item.getPrice());
            item.setSendMoney(item.getMoney());
            item.setjMoneySend(item.getjMoney());

            if (item.getId() != null) {
                updateList.add(item);
            } else {
                item.setCreateTime(delivery.getCreateTime());
                addList.add(item);
            }
        });

        if (!addList.isEmpty()) {
            deliveryDetailMapper.insertDeliveryDetailBatch(new HashMap<String, Object>() {{
                put("details", detailList);
            }});
        } else {
            updateList.forEach(item -> {
                deliveryDetailMapper.updateDeliveryDetail(item);
            });
        }

        delivery.setUpdateLock(version + 1);

        return deliveryMapper.updateDelivery(delivery);
    }

    private void insertDetails(List<DeliveryDetail> detailList) {

    }

    /**
     * 批量删除采购单
     *
     * @param ids 需要删除的采购单主键
     * @return 结果
     */
    @Override
    public int deleteDeliveryByIds(Long[] ids) {
        int i = deliveryMapper.deleteDeliveryByIds(ids);
        deliveryDetailMapper.deleteDeliveryDetailByDeliveryIds(ids);
        return i;
    }

    /**
     * 删除采购单信息
     *
     * @param id 采购单主键
     * @return 结果
     */
    @Override
    public int deleteDeliveryById(Long id) {
        return deliveryMapper.deleteDeliveryById(id);
    }

    /**
     * 竞标成功生成采购单
     */
    @Override
    @Transactional
    public void competeSuccess(Long logId) {
        ProjectLog projectLog = projectLogMapper.selectProjectLogById(logId);
        List<ProjectLogDetail> details = projectLogDetailMapper.selectProjectLogDetailList(new ProjectLogDetail() {{
            setLogId(logId);
        }});
        Map<String, ProjectLogDetail> details_map = new HashMap<>();
        details.forEach(item -> {
            String key = item.getTypeId() + "-" + item.getSpecId() + "-" + item.getBrandId();
            details_map.put(key, item);
        });

        //一个竞标记录会生成多个采购单，对应每个学校的，所以要先根据竞标记录详情关联的算量表，按照学校，分类，规格，单位，日期分组，再按照学校为单位依次新增
        List<Compute_detail_sum> sumList = new ArrayList<>(10);
        details.forEach(item -> {
            sumList.addAll(computeDetailMapper.detailSum(new HashMap<String, Object>() {{
                put("computeId", item.getComputeId());
            }}));
        });

        Map<Integer, List<Compute_detail_sum>> sumList_group = sumList.stream().collect(Collectors.groupingBy(Compute_detail_sum::getSchoolId));

        Date date = new Date();

        List<Delivery> deliveryList = new ArrayList<>(10);
        List<DeliveryDetail> detailList = new ArrayList<>(10);

        sumList_group.forEach((key, value) -> {

            //value根据日期分组
            Map<String, List<Compute_detail_sum>> value_map = value.stream().collect(Collectors.groupingBy(Compute_detail_sum::getWeek));

            value_map.forEach((key_, value_) -> {
                Delivery delivery = new Delivery();
                delivery.setId(Long.valueOf(DateUtils.dateTimeNow() + RandomStringUtils.random(4, false, true)));
                delivery.setSchoolId(Long.valueOf(key));
                delivery.setDeptId(projectLog.getDeptId());
                delivery.setUserId(projectLog.getUserId());
                try {
                    delivery.setSendTime(DateUtils.parseDate(key_ + " 00:00:00", "yyyy-MM-dd HH:mm:ss"));
                } catch (ParseException e) {
                    throw new RuntimeException(e);
                }
                delivery.setTitle(key_ + "报价单");
                delivery.setCreateTime(date);
                delivery.setLogId(logId);

                deliveryList.add(delivery);

                value_.forEach(item -> {
                    DeliveryDetail detail = new DeliveryDetail();
                    detail.setSchoolId(delivery.getSchoolId());
                    detail.setDeliveryId(delivery.getId());
                    detail.setTypeId(Long.valueOf(item.getTypeId()));
                    detail.setSpecId(Long.valueOf(item.getSpecId()));
                    detail.setBrandId(Long.valueOf(item.getBrandId()));
                    //查单价
                    String key__ = item.getTypeId() + "-" + item.getSpecId() + "-" + item.getBrandId();
                    ProjectLogDetail projectLogDetail = details_map.get(key__);
                    detail.setPrice(projectLogDetail.getPrice());

                    detail.setMoney(detail.getPrice().multiply(item.getSumNum()));
                    detail.setNum(item.getSumNum());
                    detail.setShouNum(BigDecimal.ZERO);
                    detail.setWeiNum(detail.getNum());
                    detail.setLogId(logId);
                    detail.setDoseId(deliveryMapper.selectDoseId(projectLogDetail.getComputeId()));
                    detail.setCreateTime(date);
                    detail.setjMoney(detail.getMoney());
                    detail.setjMoneySend(detail.getMoney());
                    detail.setSendPrice(detail.getPrice());
                    detail.setSendMoney(detail.getMoney());
                    detailList.add(detail);
                });

            });


        });

        deliveryList.forEach(item -> {
            BigDecimal reduce = detailList.stream().filter(obj -> obj.getDeliveryId().equals(item.getId())).map(DeliveryDetail::getMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
            item.setMoney(reduce);
            item.setType(0L);
            item.setSendMoney(item.getMoney());
            deliveryMapper.insertDelivery(item);
        });


        deliveryDetailMapper.insertDeliveryDetailBatch(new HashMap<String, Object>() {{
            put("details", detailList);
        }});

        //更新公司的竞标次数和未竞标次数
        Project project = projectMapper.selectProjectById(projectLog.getProjectId());
        //竞标结束，给未参与竞标的公司的未竞标次数加一
        sysDeptMapper.updateNotOpenCount(projectLog.getProjectId(), project.getCateId());
        //给参与竞标的公司竞标次数加一
        sysDeptMapper.updateOpenCount(projectLog.getProjectId(), project.getCateId());

    }

    /**
     * 竞标结束逻辑
     */
    @Override
    @Transactional
    public void projectEnd(Long projectId) {
        List<ProjectLog> projectLogs = projectLogMapper.selectProjectLogList_complete(new ProjectLog() {{
            setProjectId(projectId);
            setStatus(0);
        }});
        for (int i = 0; i < projectLogs.size(); i++) {
            ProjectLog projectLog = projectLogs.get(i);
            if (i == 0) {
                projectLog.setStatus(2);
                projectLog.setUpdateTime(new Date());
                projectLogMapper.updateProjectLog(projectLog);
                try {
                    competeSuccess(projectLog.getId());
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new RuntimeException(e);
                }
            } else {
                projectLog.setStatus(1);
                projectLog.setUpdateTime(new Date());
                projectLogMapper.updateProjectLog(projectLog);
            }
        }
        projectMapper.updateProject(new Project(projectId, 2));
    }
}
